{% extends '../base.html' %}
{% block css %}
<link href="/static/css/experiment.css" rel="stylesheet" type="text/css"/>
<link href="/static/css/dialog.css" rel="stylesheet" type="text/css"/>
<style>
  
</style>
{% endblock css %}

{% block content %}
<div id="experiment">
  <div class="header flex-row-between">
    <div>
      <img src='/static/icon/e_logo.png' style="width: 24px; height: 25px; margin-right: 10px;" />
      <span>e安行实训平台</span>
    </div>
    <div class="flex-row-between">
      <span>用户：{{user}}</span>
    </div>
  </div>
  <div class="content flex-row-start">
    <div class="left">
      <p style="margin-bottom: 26px; width: 25vw;">学练课：{{experiment.experiment_name}}</p>
      <div class="tabBar flex-row-between">
        <div class="tabBar-item" onclick="onTab(0)">实验介绍</div>
        <div class="tabBar-item" onclick="onTab(1)">实验指导步骤</div>
      </div>
      <div class="intro">
        {% load markdownify %}
        {% autoescape off %}
          {{experiment.intro}}
        {% endautoescape %}
      </div>
      <div class="step-info">
        <div class="step-header flex-row-between">
          <p class="step-header-title"></p>
          <img src='/static/icon/list.png' style="width: 24px; height: 25px; cursor: pointer;" onclick="toggleStepList()" />
        </div>
        <div class="step-content">
          <div class="step-list">
            {% if describe_list|length > 0 %}
              {% for index, item in describe_list %}
                {% autoescape off %}
                <div class="step-item" onclick="changeList({{index}})">{{index|add:1}}.{{item.title}}</div>
                {% endautoescape %}
              {% endfor %}
            {% endif %}
          </div>
          <div class="step-detail"></div>
        </div>
      </div>
      <div class="step-btn-bar">
        <div id="pre-btn" class="info-btn info-btn">上一步</div>
        <div id="next-btn" class="main-btn">下一步</div>
      </div>
      {% comment %} {% if experiment.instance.0.Status == 'UNCREATED' %}
      <div id="start-btn" class="l-btn" onclick="onCreate('{{experiment.instance.0.ImageId}}', this)">开始实验(时长: {{experiment.duration}}分钟)</div>
      {% elif experiment.instance.0.Status == 'STOPPED' %}
      <div class="l-btn" onclick="onInsAction('{{experiment.instance.0.InsId}}', 'start')">开始实验</div>
      {% else %}
      <div class="l-btn" style="background-color: #a6a6a6; cursor: not-allowed;">开始实验</div>
      {% endif %} {% endcomment %}
      <div class="unfold" onclick="onFold()">
        {% comment %} <i id="icon-unfold" class="layui-icon layui-icon-left" style="font-size: 30px; color: #666; line-height: 60px;"></i>  {% endcomment %}
        <img src='/static/icon/unfold.png' />
      </div>
    </div>
    <div class="right">
      <div class="i-header flex-row-between">
        <div style="cursor: pointer;" onclick="toggleFullScreen()">
          <img src='/static/icon/full_screen.png' />
          <span id="full-screen-text">全屏</span>
        </div>
        {% if experiment.instance.0.Status == 'RUNNING' %}
        <div style="font-size: 14px;">
          <span style="color: white;">学练时间剩余</span>
          <span id="cd-h"></span>: <span id="cd-m"></span>: <span id="cd-s"></span>
        </div>
        <div id="net-btn" class="primary-btn" style="display: none; background-color: #4C4C4C; color: #33FF81;" onclick="testNetSpeed('{{experiment.instance.0.PublicIpAddresses}}')">网络正常</div>
        <div id="can-trans-files" class="flex-row-between" style="font-size: 14px; width: 110px; cursor: pointer; display: none;" onclick="toggleDrawerFile('{{experiment.instance.0.PublicIpAddresses}}')">
          <img src='/static/icon/trans_file.png' />
          <span style="color: white;">传输文件</span>
        </div>
        {% comment %} <div class="primary-btn" onclick="onInsAction('{{experiment.instance.0.InsId}}', 'recovery', this)" style="display: inline-block; background-color: var(--main-color);">完成学练</div> {% endcomment %}
        <div class="primary-btn" onclick="openComplete()" style="display: inline-block; background-color: var(--main-color);">完成学练</div>
        {% comment %} <div style="cursor: pointer;" onclick="onInsAction('{{experiment.instance.0.InsId}}', 'shutdown', this)"> {% endcomment %}
        <div style="cursor: pointer;" onclick="openQuit()">
          <img src='/static/icon/out.png' style="width: 20px; height: 24px; margin-left: 11px; cursor: pointer;" />
          <span>退出</span>
        </div>
        {% endif %}
      </div>
      <div class="i-content">
        {% if experiment.instance.0.Status == 'PENDING' or experiment.instance.0.Status == 'STARTING' %}
        <div class="loading flex-column-center">
          <img src='/static/images/pc.png' />
          {% comment %} <p style="font-size: 16px; color: white">云教室电脑正在开机</p> {% endcomment %}
          <div class="flex-row-between" style="gap: 20px;">
            <div class="progress-bar">
              <div id="start-progress"></div>
            </div>
            <p id="start-text" style="font-size: 16px; color: white">30%</p>
          </div>
        </div>
        {% elif experiment.instance.0.Status == 'STOPPING' %}
        <div class="loading flex-column-center">
          <img src='/static/images/connecting.png' />
          <p style="font-size: 16px; color: white">云教室电脑正在关机</p>
        </div>
        {% elif experiment.instance.0.Status == 'RUNNING' %}
        <iframe id="vnc_container" src="" width="100%" height="100%"></iframe>
        {% else %}
        <div class="init-bar flex-column-center">
          <div class="init-dialog">
            <p>本课程限时{{experiment.duration}}分钟</p>
            <div class="init-content">
              点击“开始学练”后，将为您提供虚拟资源供您使用。结束或退出学练后，虚拟资源及学练记录将被自动释放。
            </div>
          </div>
          {% if experiment.instance.0.Status == 'UNCREATED' %}
          <div id="start-btn" class="init-btn" onclick="onCreate('{{experiment.instance.0.ImageId}}', this)">开始学练</div>
          {% elif experiment.instance.0.Status == 'STOPPED' %}
          <div id="start-btn" class="init-btn" onclick="onInsAction('{{experiment.instance.0.InsId}}', 'start')">开始学练</div>
          {% endif %}
        </div>
        {% endif %}
        <div class="drawer-file">
          <div class="drawer-tab flex-row-start">
            <div class="drawer-tabItem" onclick="onDrawerTab(0)">上传文件</div>
            <div class="drawer-tabItem" onclick="onDrawerTab(1)">导出文件</div>
          </div>
          <div class="drawer-upload">
            <div class="drawer-list-item flex-row-start">
              <img src='/static/icon/pc_icon.png' style="margin-right: 10px;" />
              <span>本地文件上传</span>
              <button id="uploadButton" class="primary-btn" style="margin-left: auto;">立即上传</button>
              <input type="file" id="fileInput" style="display: none;" accept="*">
            </div>
          </div>
          <div class="drawer-export">
            <div class="export-bar flex-column-start">
              <p>选择要导出的文件</p>
              <p>1.将文件拖至桌面“文件中转站”；</p>
              <p>2.返回本页面，选择文件中转站中要导出的文件；</p>
              <p>3.点击“导出”按钮，将文件导出至本地。</p>
            </div>
            <div class="export-bar flex-column-start">
              <p>选择要导出的文件</p>
              <p style="color: var(--main-color);">仅支持导出以下格式文件：.doc/.docx/.xls/.pdf/.txt</p>
              <div id="files-options" style="max-height: 550px; overflow-y: auto;"></div>
              <div class="main-btn" onclick="downFiles('{{experiment.instance.0.PublicIpAddresses}}')">导出</div>
            </div>
          </div>
          <div class="drawer-footer-0 flex-row-start">
            <p>总空间：<span id="free-disk" style="color: var(--main-color)">200.00</span>可用/共<span id="total-disk">200</span></p>
            <p style="margin-left: auto;">单个文件最大<span style="color: var(--main-color)">100</span>MB</p>
          </div>
          <div class="drawer-footer-1 flex-row-start">
            <p>导出文件总大小不超过<span style="color: var(--main-color)">100</span>MB</p>
          </div>
        </div>
        {% comment %} dialog {% endcomment %}
        <div id="net-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <img src='/static/icon/loading.png' style="margin-right: 15px;" />
            <p id="net-speed-testing">网速检测中......</p>
            <img src='/static/icon/close.png' style="margin-left: auto;" onclick="closeDialog()" />
          </div>
          <div class="dialog-info">
            <p id="download-text" style="color: #009DFF; display: none;">网络下载速度为0KB/s</p>
            <p id="upload-text" style="color: #009DFF; display: none;">网络上传速度为0KB/s</p>
            <p style="color: #009DFF;">若网速低于350KB/s。将影响您的使用体验</p>
          </div>
          <div class="dialog-footer">
            <div class="main-btn" onclick="closeDialog()">确定</div>
          </div>
        </div>
        {% comment %} 学练时间已到 {% endcomment %}
        <div id="out-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>学练结束</p>
          </div>
          <div class="dialog-info">
            <p style="color: #009DFF; font-size: 18px; font-weight: 700;">
              <img src='/static/icon/bettery.png' style="margin-right: 15px;" />
              本次学练结束
            </p>
            <p>您的本次学练时间已达课程规定的{{experiment.duration}}分钟，学练资源将自动释放，感谢您的使用！</p>
          </div>
          <div class="dialog-footer">
            <div class="main-btn" onclick="onRecovery()">确定</div>
          </div>
        </div>
        {% comment %} 退出关闭实例 {% endcomment %}
        <div id="quit-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>确认退出</p>
          </div>
          <div class="dialog-info">
            <p style="color: #FF6200; font-size: 18px; font-weight: 700;">
              确认要退出吗？
            </p>
            <p>退出后，系统仍会为您保留已开通的云资源，您可以再次点击”开始学练“进行学习。</p>
          </div>
          <div class="dialog-footer">
            <div class="info-btn" style="margin-right: 15px; cursor: pointer;" onclick="closeDialog()">取消</div>
            <div class="main-btn" onclick="onShutdown()">确定</div>
          </div>
        </div>
        {% comment %} 完成学练 {% endcomment %}
        <div id="complete-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>完成确认</p>
          </div>
          <div class="dialog-info">
            <p style="color: #009DFF; font-size: 18px; font-weight: 700;">
              <img src='/static/icon/complete.png' style="margin-right: 15px;" />
              恭喜您完成学练
            </p>
            <p>系统将释放已为您开通的云资源，您的学练状态将被标记为”已完成“，但学练记录不会被保存。</p>
          </div>
          <div class="dialog-footer">
            <div class="info-btn" style="margin-right: 15px; cursor: pointer;" onclick="closeDialog()">取消</div>
            <div class="main-btn" onclick="onRecovery()">确认完成</div>
          </div>
        </div>
        {% comment %} 连接中断提示 {% endcomment %}
        <div id="notice-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>创建远程连接会话失败</p>
          </div>
          <div class="dialog-info">
            <p style="color: #CC0000; font-size: 18px; font-weight: 700; text-align: center;">
              <img src='/static/icon/notice.png' style="margin-right: 15px;" />
              连接失败
            </p>
            <p style="text-align: center;">请检查网络连接或者浏览器代理设置。</p>
          </div>
          <div class="dialog-footer" style="justify-content: center;">
            <div class="main-btn" onclick="location.reload()">重新连接</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<div id="loading-bar" class="layui-progress" lay-filter="demo" lay-showPercent="true">
  <div class="layui-progress-bar" lay-percent="0%"></div>
</div>
<div id="dialog-mask" class="dialog-mask" style="display: none; width: 100vw; height: 100vh; position: fixed;"></div>
{% endblock content %}

{% block script %}
<script src="/static/study/layui/layui.js" charset="utf-8"></script>
<script src="/static/js/tools.js"></script>
<script src="/static/js/experiment.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script>
<script>
  /*
  'UNCREATED': '未创建',
  'PENDING': '操作中..',
  'LAUNCH_FAILED': '创建失败',
  'RUNNING': '运行中..',
  'STOPPED': '关机',
  'STARTING': '开机中..',
  'STOPPING': '关机中..',
  'REBOOTING': '重启中..',
  'SHUTDOWN': '停止待销毁',
  'TERMINATING': '销毁中..'
  */
  let unfold = false
  let drawerShow = false
  let loading = false
  let novnc_url = ""
  let imageId = ""
  let link_count = 0
  let start_pc = 0
  let isFullScreen = false
  let isStepList = false
  let canTransFile = false
  let isNetTesting = false
  let iscountDown = false
  let describeList = []
  let selectedFiles = []
  var layer
  var element
  var btnHanleing = false
  layui.use('layer', function () {
    layer = layui.layer;
  });
  layui.use('element', function () {
    element = layui.element;
  });

  window.onload = function() {

    let isConnect = false

    setTimeout(() => {
      if(!isConnect) {
        document.getElementById("notice-dialog").style.display = "block"
      }
    }, 5000)

    function onNetLink(ip) {
      setTimeout(() => netLink(ip), 1500)
      setInterval(() => netLink(ip), 5 * 60 * 1000)
    }

    setTimeout(() => {
      if({{error_code}} == -2) {
        location.reload()
      }else if({{error_code}} == 2) {
        window.location.href = "/experiment/buy/" + {{experiment.id}} + "/"
      }
  
      let instanceData = null;
      try {
        if({{experiment.instance.0|safe}}) {
          instanceData = {{experiment.instance.0|safe}}
        }
      }catch (e) {
        location.reload();
      }
      console.log('~views Status', instanceData)
      isConnect = true
      //console.log('~describe_list', {{describe_list|safe}})
  
      if({{describe_list|safe}}) {
        let arr = {{describe_list|safe}}
        describeList = {{describe_list|safe}}
        /*
        document.getElementsByClassName('step-header-title')[0].innerHTML = arr[0].title
        document.getElementsByClassName('step-detail')[0].innerHTML = arr[0].detail
        document.getElementsByClassName('step-item')[0].style.color = "var(--main-color)"
        document.getElementsByClassName('step-item')[0].style.backgroundColor = "#665347"
        */
        imageId = instanceData.ImageId
        changeList(0, arr, instanceData.ImageId)
      }
  
      function loadProgress () {
        if(start_pc < 7) {
          setTimeout(() => {
            document.getElementById('start-progress').style.width = 30 + start_pc * 10 + '%'
            document.getElementById('start-text').innerText= 30 + start_pc * 10 + '%'
            start_pc++
            loadProgress()
          }, 11000)
        }else if(start_pc >= 7) {
          location.reload()
        }
      }
  
      function loadStopping () {
        if(start_pc < 5) {
          setTimeout(() => {
            start_pc++
            loadStopping()
          }, 2000)
        }else if(start_pc >= 5) {
          location.reload()
        }
      }
  
      if(instanceData.Status == 'PENDING') {
        loadProgress()
      }else if(instanceData.Status == 'STOPPING' || instanceData.Status == 'STOPPING') {
        loadStopping()
      }else if(instanceData.Status == 'TERMINATING') {
        location.reload()
      }
  
      let tabItem = document.getElementsByClassName("tabBar-item");
      tabItem[0].style.backgroundColor = "var(--main-color)";
      let drawTabItem = document.getElementsByClassName("drawer-tabItem");
      drawTabItem[0].style.color = "var(--main-color)";
      drawTabItem[0].style.borderBottom = "2px var(--main-color) solid";
  
      setTimeout(function () {
        if (window.navigator.userAgent.indexOf("JavaFX") >= 0) {
          logger(window.navigator.userAgent.indexOf("JavaFX"))
          logger(app.login.toString())
          // location.href = location.href 
        }
      }, 1000)
  
      function loadStatus () {
        var vmsStr = ""
        var id = {{ experiment.id }}
      
        //var vnccode = "{{vnccode}}"
        models.experimentModel.item({{ experiment.id }}, function (res) {
          if (res.error_code == 0) {
            //倒计时
            if (instanceData.Status == 'RUNNING' && document.getElementById('cd-h') && res.data.instance[0].create_st && !iscountDown) {
              //interval = setInterval(reverseTs, 1000);
              iscountDown = true;
              layui.use('util', function(){
                var util = layui.util;
                var endTime = localStorage.getItem("countdown-data") ? (JSON.parse(localStorage.getItem("countdown-data"))[res.data.instance[0].InsId]) : (new Date().getTime() + {{experiment.duration}} * 60 * 1000)
                //支持毫秒时间戳
                var serverTime = new Date().getTime();
                util.countdown(endTime, serverTime, function(date,serverTime,timer){
                  var str = date[0] + '天' + date[1] + '时' + date[2] + '分' + date[3]+'秒'
                  document.getElementById('cd-h').innerText = date[1]
                  document.getElementById('cd-m').innerText = date[2]
                  document.getElementById('cd-s').innerText = date[3]
                  // 学练时间剩余0
                  if((date[1] == 0 && date[2] == 0 && date[3] == 1) || (endTime - serverTime < 0)){
                    document.getElementById('out-dialog').style.display = "block"
                    document.getElementById('dialog-mask').style.display = "block"
                    setTimeout(() => onRecovery(), 10000)
                  }
                })
              })
            }
            //倒计时缓存
            if(res.data && res.data.instance[0].create_st) {
              //console.log('~create_st', new Date(res.data.instance[0].create_st).getTime())
              if(localStorage.getItem("countdown-data")) {
                let obj = JSON.parse(localStorage.getItem("countdown-data"))
                let timeLeft = new Date(res.data.instance[0].create_st).getTime() + ({{experiment.duration}} * 60 * 1000)
                obj[`${res.data.instance[0].InsId}`] = timeLeft
                localStorage.setItem("countdown-data", JSON.stringify(obj))
              }else {
                let obj = {}
                let timeLeft = new Date(res.data.instance[0].create_st).getTime() + ({{experiment.duration}} * 60 * 1000)
                obj[`${res.data.instance[0].InsId}`] = timeLeft
                localStorage.setItem("countdown-data", JSON.stringify(obj))
                location.reload()
              }
            }
            //console.log('~res.data', res.data)
            if(res.data.vnc_url && link_count == 0) {
              //console.log('~res.data.vnc_url', res.data.vnc_url)
              let icd = res.data.instance[0].doraemon.slice(res.data.instance[0].doraemon.indexOf('A'), res.data.instance[0].doraemon.indexOf('nr') + 2)
              novnc_url = res.data.vnc_url + '?asd=&' + encodeURIComponent('abc=123@;hash&kk=替代方式$%^&pcode=' + res.data.instance[0].doraemon)
              autoGoVnc();
              link_count++;
            }
            if(!canTransFile && instanceData.Status == 'RUNNING') {
              //绑定虚拟机接口
              getDownloadFiles(res.data.instance[0].PublicIpAddresses)
              onUpload(res.data.instance[0].PublicIpAddresses)
              calVMDisk(res.data.instance[0].PublicIpAddresses)
              onNetLink(res.data.instance[0].PublicIpAddresses)
              //canTransFile = true
            }
            //console.log('~status', instanceData.Status)
            if(instanceData.Status == 'PENDING' && start_pc < 7) {
              document.getElementById('start-progress').style.width = 30 + start_pc * 10 + '%'
              document.getElementById('start-text').innerText= 30 + start_pc * 10 + '%'
              start_pc ++
            }else if(instanceData.Status == 'PENDING' && start_pc >= 7) {
              location.reload()
            }
            let inTimer = null; 
            if(res.data.instance[0].Status == 'PENDING' || res.data.instance[0].Status == 'STARTING') {
              inTimer = setInterval(function () {
                loadStatus()
              }, 15000)
              //setTimeout(() => location.reload(), 5000)
              return;
            }else {
              clearInterval(inTimer)
            }
            if(!res.data.vnc_url){
              return setTimeout(function () {
                loadStatus()
              }, 5000) 
            }
          }else {
            console.log('no res')
          }
          return setTimeout(function () {
            loadStatus()
          }, 5000) 
        }, function (err) {
          console.log('~loadStatus err', err)
          if(err.error_code && err.error_code == -2) {
            location.reload()
          }
          //location.reload()
        })
      }

      loadStatus()
    }, 3000)
  }

  function onCreate(ImageId, node) {
    console.log(ImageId, event)
    if (loading) return;
    if (btnHanleing) return;
    layer.confirm('确定创建虚拟机实例？', { title: '提示' }, function (index) {
      startLoading(index)
      let opsEl = document.getElementById('start-btn')
      opsEl.style.cursor = "not-allowed"
      opsEl.style.backgroundColor = "#e6e6e6"
      models.insModel.action({
        action: 'create',
        imageId: ImageId,
        envId: {{ experiment.environment.id }}
      }, function(res) {
        console.log('~create res', res)
        endLoading()
        
        btnHanleing = true
        setTimeout(() => location.reload(), 3000)
        layer.msg(err.message, {
          icon: 1,
          time: 3000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
          // location.href = location.href + "#login-vm"
        });
      }, function(err) {
        endLoading()
        layer.msg(err.message, {
          icon: 1,
          time: 3000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
        });
      })
    }, function(cancel) {
      loading = false
      console.log('cancel', cancel)
    })
  }
  
  function onInsAction(InsId, action, node) {
    console.log(InsId, event)
    //not-allowed
    if (loading) return;
    if (btnHanleing) return;
    layer.confirm(`确定${action}虚拟机实例？`, { title: '提示' }, function (index) {
      startLoading(index)
      models.insModel.action({
        action: action,
        insId: InsId,
        envId: {{ experiment.environment.id }}
      }, function(res) {
        endLoading()
        let opsEls = document.getElementsByClassName('btn-short')
        for(let el of opsEls) {
          el.style.cursor = "not-allowed"
          el.style.backgroundColor = "#e6e6e6"
        }
        btnHanleing = true
        // todo 延时3秒完成
        layer.msg(action + `成功，${action == 'start' ? '15' : '3'}秒后刷新页面`, {
          icon: 1,
          time: action == 'start' ? 15000 : 5000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
          setTimeout(() => location.reload(), action == 'start' ? 15000 : 5000)
          // location.href = location.href + "#login-vm"
        });
      }, function(err) {
        endLoading()
        layer.msg(err.message, {
          icon: 1,
          time: 5000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
        });
      })
        }, function(cancel) {
        loading = false
        console.log('cancel', cancel)
      })
  }

  function testNetSpeed(ip) {
    document.getElementById("net-dialog").style.display = "block"
    document.getElementById("download-text").style.display = "none"
    document.getElementById("upload-text").style.display = "none"
    document.getElementById("net-speed-testing").innerHTML = "网速检测中......"
    if(!isNetTesting) {
      netLink(ip)
    }
  }

  function closeDialog() {
    document.getElementById("net-dialog").style.display = "none"
    document.getElementById("out-dialog").style.display = "none"
    document.getElementById("quit-dialog").style.display = "none"
    document.getElementById("complete-dialog").style.display = "none"
  }

  function openQuit() {
    document.getElementById("quit-dialog").style.display = "block"
  }

  function openComplete() {
    document.getElementById("complete-dialog").style.display = "block"
  }

  function onShutdown() {
    let instanceDate = {{experiment.instance.0|safe}};
    models.insModel.action({
      action: 'shutdown',
      insId: instanceDate.InsId,
      envId: {{ experiment.environment.id }}
    }, function(res) {
      location.reload()
    }, function(err) {
      endLoading()
      setTimeout(() => location.reload(), 10000)
    })
  }

  function onRecovery() {
    let instanceDate = {{experiment.instance.0|safe}};
    models.insModel.action({
      action: 'recovery',
      insId: instanceDate.InsId,
      envId: {{ experiment.environment.id }}
    }, function(res) {
      location.reload()
    }, function(err) {
      endLoading()
      setTimeout(() => location.reload(), 10000)
    })
  }
</script>
{% endblock script %}